package reporte;

import org.joda.time.DateTime;

import exceptions.ParametrosMalColocadosException;
import productosYPresentaciones.Producto;
import reporte.filtros.*;
import ventas.Venta;

/**
 * Clase que se encarga de crear los filtros de ventas para
 * el reporte.
 * @author Octavio Nicolas Pompilio
 *
 */
public class BuilderFiltroVenta {

	private Filtro<Venta> filtroVenta;
	
	/**
	 * Contructor del Builder.
	 * Sirve para instanciar los metodos static
	 * @param filtro
	 * Es el filtro del cual estara compuesto
	 */
	protected BuilderFiltroVenta(Filtro<Venta> filtro){
		this.filtroVenta = filtro;
	}
	
	/**
	 * Crea un constructor del filtro que siempre pasa todo 
	 * @return
	 * Un Builder que dejara pasar todas las ventas.
	 */
	public static BuilderFiltroVenta filtroTrue(){
		return new BuilderFiltroVenta(new FiltroTrue<Venta>());
	}
	
	/**
	 * Crea un constructor del filtro que deja pasar aquellas ventas
	 * que tengan su fecha de creacion posterior a la fecha indicada. 
	 * @param fecha
	 * La fecha desde la que comenzara a contar el filtro.
	 * @return
	 * Un Builder que dejara pasar ventas con sus fechas mayores a la condicion
	 */
	public static BuilderFiltroVenta filtroDesdeFecha(DateTime fecha){
		return new BuilderFiltroVenta(new FiltroVentasDesdeFecha(fecha));
	}
	
	/**
	 * Crea un constructor del filtro que deja pasar aquellas ventas
	 * que tengan su fecha de creacion anterior a la fecha indicada. 
	 * @param fecha
	 * La fecha hasta la que contara el filtro.
	 * @return
	 * Un Builder que dejara pasar ventas con sus fechas menores a la condicion
	 */
	public static BuilderFiltroVenta filtroHastaFecha(DateTime fecha){
		return new BuilderFiltroVenta(new FiltroVentasHastaFecha(fecha));
	}
	
	/**
	 * Crea un constructor del filtro que deja pasar aquellas ventas
	 * que tengan su monto mayor al monto indicado. 
	 * @param monto
	 * El monto desde donde contara el filtro.
	 * @return
	 * Un Builder que dejara pasar ventas con sus montos mayores a la condicion
	 */
	public static BuilderFiltroVenta filtroDesdeMonto(float monto){
		return new BuilderFiltroVenta(new FiltroVentasDesdeMonto(monto));
	}
	
	/**
	 * Crea un constructor del filtro que deja pasar aquellas ventas
	 * que tengan su monto menor al monto indicado. 
	 * @param monto
	 * El monto hasta donde contara el filtro.
	 * @return
	 * Un Builder que dejara pasar ventas con sus montos menores a la condicion
	 */
	public static BuilderFiltroVenta filtroHastaMonto(float monto){
		return new BuilderFiltroVenta(new FiltroVentasHastaMonto(monto));
	}
	
	/**
	 * Crea un constructor del filtro que dejara pasar aquellas ventas
	 * que tengan al producto especificado.
	 * @param producto
	 * El producto que se toma como referencia.
	 * @return
	 * Un Builder que dejara pasar ventas con ese producto.
	 */
	public static BuilderFiltroVenta filtroPorProducto(Producto producto){
		return new BuilderFiltroVenta(new FiltroVentasPorProducto(producto));
	}
	
	/**
	 * Crea un constructor del filtro que dejara pasar aquellas ventas cuya 
	 * fecha de creacion se encuentra entre ambas fechas.
	 * @param fechaI
	 * La fecha inicial desde donde comenzara a contar el filtro.
	 * @param fechaF
	 * La fecha final hasta donde contara el filtro.
	 * @return
	 * Un Builder que dejara pasar a las ventas entre esas fechas.
	 * @throws ParametrosMalColocadosException
	 * Si las fechas estan mal ingresadas, se lanza la excepcion.
	 * Se debe arreglar cambiando las fechas de lugar.
	 */
	public static BuilderFiltroVenta filtroEntreFechas(DateTime fechaI,DateTime fechaF) throws ParametrosMalColocadosException{
		if( fechaI.isAfter(fechaF) )
			throw new ParametrosMalColocadosException("La fecha inicial esta despues de la final");
		else
		return filtroDesdeFecha(fechaI).and(filtroHastaFecha(fechaF));
	}
	
	/**
	 * Crea un constructor del filtro que dejara pasar aquellas ventas cuya 
	 * fecha de creacion se encuentra entre ambas fechas.
	 * @param fechaI
	 * La fecha inicial desde donde comenzara a contar el filtro.
	 * @param fechaF
	 * La fecha final hasta donde contara el filtro.
	 * @return
	 * Un Builder que dejara pasar a las ventas entre esas fechas.
	 * @throws ParametrosMalColocadosException
	 * Si las fechas estan mal ingresadas, se lanza la excepcion.
	 * Se debe arreglar cambiando las fechas de lugar.
	 */
	public static BuilderFiltroVenta filtroEntreMontos(float montoI,float montoF) throws ParametrosMalColocadosException{
		if( montoI > montoF )
			throw new ParametrosMalColocadosException("El monto inicial es mayor al monto final");
		else
		return filtroDesdeMonto(montoI).and(filtroHastaMonto(montoF));
	}
	
	public static BuilderFiltroVenta filtroConEnvios(){
		return new BuilderFiltroVenta( new FiltroVentasConEnvios() );
	}

	/**
	 * Crea un constructor del filtro que niega la condicion del filtro
	 * @return
	 * Un Builder que nego la condicion del Builder anterior.
	 */
	public BuilderFiltroVenta neg(){
		return new BuilderFiltroVenta(new FiltroNot<Venta>
				(this.build()));
	}
	
	/**
	 * Crea un constructor del filtro que debe dejar pasar ventas 
	 * que cumplan ambos constructores.
	 * @param builder
	 * El builder con el que se unira.
	 * @return
	 * Un Builder que hace un And entre las condiciones de los builders. 
	 */
	public BuilderFiltroVenta and(BuilderFiltroVenta builder){
		return new BuilderFiltroVenta(new FiltroAnd<Venta>
				(this.build(),builder.build()) );
	}
	
	/**
	 * Crea un constructor del filtro que debe dejar pasar ventas 
	 * que cumplan algun constructor.
	 * @param builder
	 * El builder con el que se unira.
	 * @return
	 * Un Builder que hace un Or entre las condiciones de los builders. 
	 */
	public BuilderFiltroVenta or(BuilderFiltroVenta builder){
		return new BuilderFiltroVenta(new FiltroOr<Venta>
				(this.build(),builder.build()) );
	}
	
	/**
	 * Construye el filtro en base al historial del Builder.
	 * @return
	 * Un filtro con las mismas condiciones de filtro que el builder.
	 */
	public Filtro<Venta> build(){
		return this.filtroVenta;
	}
}
